Skip to content

feat(swap): /swap page powered by 0x Swap API v2 - #92

Merged
sktbrd merged 3 commits into
r4topunk:mainfrom
sktbrd:feat/swap-page-0x
May 1, 2026
Merged

feat(swap): /swap page powered by 0x Swap API v2#92
sktbrd merged 3 commits into
r4topunk:mainfrom
sktbrd:feat/swap-page-0x

Conversation

@sktbrd

@sktbrd sktbrd commented May 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Ships a new /swap page that lets users trade ETH, WETH, USDC, GNARS, and a few other Base ERC-20s through the 0x Swap API v2, routed via allowance-holder/price and allowance-holder/quote.
  • Two server-only proxy routes (/api/0x/price, /api/0x/quote) hold the ZEROX_API_KEY and inject opt-in affiliate fee params (swapFeeRecipient/swapFeeBps/swapFeeToken) only when the client passes ?fee=1 AND GNARS_FEE_RECIPIENT is configured.
  • Header nav: collapses Treasury under a new Money dropdown that also hosts the Swap entry.

Changes

  • src/app/swap/page.tsx — server component, page metadata + canonical, renders <SwapWidget />.
  • src/app/swap/SwapWidget.tsx — client component with token pickers (shadcn Dialog), debounced 0x indicative price, ERC-20 approval flow (prepareContractCall + thirdweb sendTransaction), swap execution via prepareTransaction on the firm 0x quote, network-fee display, wrong-network "Switch to Base" CTA, and an opt-in "Support Gnars treasury (0.5% fee)" checkbox (default checked).
  • src/app/api/0x/price/route.ts & src/app/api/0x/quote/route.ts — Edge-style proxy routes; identical fee-injection logic so the price preview and the firm quote stay consistent.
  • src/components/layout/DaoHeader.tsx — converts the Treasury top-level link into a Money dropdown containing Treasury and Swap.
  • env.example — documents ZEROX_API_KEY, GNARS_FEE_RECIPIENT, GNARS_FEE_BPS.
  • docs/integrations/swap.md — architecture, flow, env vars, fee model, and intentional deviations from the SkateHive reference. docs/INDEX.md updated to point at it.

Architectural notes (vs. SkateHive reference)

  • Single-chain. Base only — chainId is hardcoded to 8453.
  • No Hive / Zora bonding-curve routes. Plain 0x ERC-20 swaps only.
  • shadcn / Tailwind, not Chakra. Card / Button / Input / Dialog / Checkbox / Tooltip / sonner toasts.
  • thirdweb signing, not wagmi writes. Approvals and swaps both go through useWriteAccount() so the SA-vs-EOA view-mode toggle keeps working.
  • Fixed token list. ETH / WETH / USDC / GNARS / DEGEN / HIGHER. Adding tokens is a one-line edit.

Required env vars

Var Where Notes
ZEROX_API_KEY server-only 0x API key. Required — proxy returns 500 without it.
GNARS_FEE_RECIPIENT server-only Affiliate fee recipient. Optional — leave blank to disable.
GNARS_FEE_BPS server-only Default 50 (0.5%).

Test plan

  • Vercel preview loads /swap cleanly; metadata shows "Swap — Gnars DAO".
  • Token pickers open, "Popular" row shows ETH / USDC / GNARS / DEGEN, search filters by symbol/name/address, the currently-selected counterpart token is greyed out.
  • Connect wallet → enter 0.001 ETH → buy GNARS: indicative price renders within ~600ms, network fee shows, "Swap" button enables.
  • Disconnect → CTA shows the "Connect your wallet to swap" empty state.
  • Switch wallet to Ethereum → CTA flips to "Switch to Base" and successfully switches.
  • USDC → GNARS first run shows "Approve USDC", clicking signs the approval; on confirmation "Swap" becomes enabled.
  • Untick "Support Gnars treasury" — request to /api/0x/price no longer carries fee=1; ticking again puts it back.
  • Header: Money dropdown contains Treasury + Swap (NEW!) on desktop and in the mobile sheet.
  • pnpm lint clean (1 pre-existing warning in BountiesView.tsx).
  • pnpm build clean — /swap listed as a static route.

Generated with Claude Code

Adds an ERC-20 swap experience on Base with best execution across 150+ DEXes.

- /api/0x/price + /api/0x/quote proxy 0x's allowance-holder endpoints,
  keeping ZEROX_API_KEY server-side and injecting affiliate fee params
  (swapFeeRecipient/swapFeeBps/swapFeeToken) only when the client opts in
  with ?fee=1 and GNARS_FEE_RECIPIENT is configured.
- /swap renders SwapWidget: token pickers, debounced indicative price,
  ERC-20 approval flow (prepareContractCall + thirdweb sendTransaction),
  swap execution via prepareTransaction on the firm 0x quote, network
  fee display, wrong-network "Switch to Base" CTA, and an opt-in
  "Support Gnars treasury" checkbox (default checked).
- Default token list: ETH / WETH / USDC / GNARS / DEGEN / HIGHER on Base.
- Header nav: collapses Treasury under a new "Money" dropdown that also
  hosts the Swap entry.
- Docs: docs/integrations/swap.md describes the architecture, env vars,
  and fee model; INDEX.md updated to point at it.
- env.example: ZEROX_API_KEY, GNARS_FEE_RECIPIENT, GNARS_FEE_BPS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented May 1, 2026

Copy link
Copy Markdown

@sktbrd is attempting to deploy a commit to the r4to's projects Team on Vercel.

A member of the Team first needs to authorize it.

Drops GNARS_FEE_RECIPIENT and GNARS_FEE_BPS env vars in favor of:
- swapFeeRecipient -> DAO_ADDRESSES.treasury (already canonical in config)
- swapFeeBps      -> SWAP_FEE_BPS = 50 (new constant in src/lib/config.ts)

ZEROX_API_KEY remains the only required env var. Fee destination and rate
now ship with the code so they're auditable in git rather than hidden in
deploy-time secrets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented May 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gnars-shadcn Ready Ready Preview, Comment May 1, 2026 3:09pm

Request Review

@sktbrd
sktbrd merged commit 2f9705a into r4topunk:main May 1, 2026
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant